package com.bygf.curve;

import com.bygf.curve.panel.ChartPanel;
import java.awt.AlphaComposite;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;

/**
 * 区域曲线
 *
 * @author sunyupei
 */
public class AreaCurve extends Curve {

    //X数值集合
    List<Double> XValueList = new ArrayList<>();
    //Y数值集合
    List<Double> YValueList = new ArrayList<>();
    //曲线透明度0-1，0-完全透明，1-完全不透明
    private float alpha = 0.5F;

    /**
     * 构造方法
     *
     * @param name 曲线名称
     * @param alpha 填充区域的透明度
     */
    public AreaCurve(String name, float alpha) {
        this.name = name;
        this.setAlpha(alpha);
    }

    /**
     * 曲线绘制自身方法
     *
     * @param g
     * @param chartPanel
     */
    @Override
    public void draw(Graphics2D g, ChartPanel chartPanel) {
        g.setColor(render.getColor());
        g.setStroke(render.getStroke());
        //数值转像素
        this.valueToPix(chartPanel);
        Path2D path = new Path2D.Double();
        for (int i = 0; i < XPixList.size(); i++) {
            if (i == 0) {
                path.moveTo(XPixList.get(i), chartPanel.getCurvePanel().getHeight());
            }
            path.lineTo(XPixList.get(i), YPixList.get(i));
            if (i == XPixList.size() - 1) {
                path.lineTo(XPixList.get(i), chartPanel.getCurvePanel().getHeight());
            }
        }
        path.closePath();
        Composite backComposite = g.getComposite();
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
        g.draw(path);
        g.fill(path);
        Rectangle2D rectLast = null;
        if (render.isShapeVisible()) {
            double width = render.getStroke().getLineWidth() * 4;
            for (int i = 0; i < XPixList.size(); i++) {
                Rectangle2D rect = new Rectangle2D.Double(XPixList.get(i) - width / 2, YPixList.get(i) - width / 2, width, width);
                if (rectLast == null) {
                    rectLast = rect;
                }
                if ((rect.getMinX() - rectLast.getMaxX()) > 1) {
                    g.fill(rect);
                    rectLast = rect;
                }
            }
        }
        g.setComposite(backComposite);
    }

    @Override
    public void valueToPix(ChartPanel chartPanel) {
        XPixList.clear();
        YPixList.clear();
        valueIndex = -1;
        for (int i = 0; i < XValueList.size(); i++) {
            //过滤在当前X轴坐标范围内不会绘制出来的数据，用于节省绘制时间
            if (XValueList.get(i) < chartPanel.getXAxis().getStartValueNow()
                    || XValueList.get(i) > chartPanel.getXAxis().getEndValueNow()) {
                continue;
            }
            double x = chartPanel.getXAxis().valueToPix(XValueList.get(i));
            double y;
            if (isUsedY2Axis()) {
                y = chartPanel.getY2Axis().valueToPix(YValueList.get(i));
            } else {
                y = chartPanel.getYAxis().valueToPix(YValueList.get(i));
            }
            XPixList.add(x);
            YPixList.add(y);
            if (valueIndex == -1) {
                valueIndex = i;
            }
        }
    }

    /**
     * 往曲线中增加数值
     *
     * @param xValue
     * @param yValue
     */
    public void addItem(double xValue, double yValue) {
        XValueList.add(xValue);
        YValueList.add(yValue);
    }

    @Override
    public String getToolTip(Point point) {
        for (int i = 0; i < XPixList.size(); i++) {
            Point2D pointTemp = new Point2D.Double(XPixList.get(i), YPixList.get(i));
            if (pointTemp.distance(point) < getRender().getStroke().getLineWidth() * 2) {
                ArrayList list = new ArrayList();
                list.add(name);
                list.add(XValueList.get(i + valueIndex));
                list.add(YValueList.get(i + valueIndex));
                return toolTipFormat.format(list);
            }
        }
        return null;
    }

    /**
     * @return the alpha
     */
    public float getAlpha() {
        return alpha;
    }

    /**
     * @param alpha the alpha to set
     */
    public void setAlpha(float alpha) {
        if (alpha >= 0 && alpha <= 1) {
            this.alpha = alpha;
        } else {
            throw new IllegalArgumentException("透明度数值必须在0-1之间");
        }
    }
}
